package cn.yx.framework.exception;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Created by Administrator on 2017-02-10.
 */
public abstract class BasicException extends Exception {
    private static final Logger logger = LoggerFactory.getLogger(BasicException.class);
    public static final int CODE_UNKNOWN_EXCEPTION = 5000;
    public static final int CODE_ILLEGAL_ARGUMENT_EXCEPTION = 5001;
    public static final int CODE_RUNTIME_EXCEPTION = 5002;
    public static final int CODE_METHOD_ARGUMENT_CONVERSION_NOT_SUPPORTED_EXCEPTION = 4002;
    public static final int CODE_HTTP_MEDIA_TYPE_NOT_SUPPORTED_EXCEPTION = 4001;
    public static final int CODE_HTTP_REQUEST_METHOD_NOT_SUPPORT_EXCEPTION = 5405;
    public static final int CODE_HTTP_MEDIATYPE_NOT_ACCEPTABLE_EXCEPTION = 4006;
    private static final String EXCEPTION_TRACE_FILTER = "cn.ucox";
    private Map<String, Object> report;

    BasicException(final int errorCode, final String message) {
        super(message);
        this.report = new HashMap(4) {
            {
                this.put("code", Integer.valueOf(errorCode));
                this.put("msg", message);
                this.put("time", new Date());
                String filter = BasicException.this.getFilter();
                if(BasicException.logger.isDebugEnabled()) {
                    this.put("data", BasicException.this.getData());
                    if(StringUtils.isEmpty(filter)) {
                        this.put("trace", BasicException.this.getStackTrace());
                    } else {
                        this.put("trace", Stream.of(BasicException.this.getStackTrace()).filter((trace) -> {
                            return trace.getClassName().startsWith(filter);
                        }).collect(Collectors.toList()));
                        this.put("format", BasicException.getFormatTrace(this.get("trace")));
                    }
                }

            }
        };
    }

    public Map<String, Object> getReport() {
        return this.report;
    }

    public static String getFormatTrace(Object exception) {
        if(null == exception) {
            return "";
        } else {
            StackTraceElement[] traces = (StackTraceElement[])((StackTraceElement[])exception);
            StringBuilder err = new StringBuilder();
            int level = 0;
            StackTraceElement[] var4 = traces;
            int var5 = traces.length;

            for(int var6 = 0; var6 < var5; ++var6) {
                StackTraceElement traceElement = var4[var6];
                ++level;
                err.append("\n|");

                for(int j = 0; j < level; ++j) {
                    err.append("_");
                }

                err.append(String.format("%s.%s() ->%d", new Object[]{traceElement.getClassName(), traceElement.getMethodName(), Integer.valueOf(traceElement.getLineNumber())}));
            }

            return err.toString();
        }
    }

    protected String getFilter() {
        return "cn.ucox";
    }

    protected abstract Object getData();
}
